﻿#include "bootstrap.h"
#include "ui_bootstrap.h"

Bootstrap::Bootstrap(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Bootstrap)
{
    ui->setupUi(this);

    dsEditor=nullptr;
    receiver=nullptr;
    dsTable=P_DATASOURCE;

    sharedMemory=new QSharedMemory(SHM_KEY,this);
    fetchData();
    createTray();
    startTimer(AUTOSYNC_INTERVAL);
    appendLog(QString(SP_NAME) + " Started");
    move(400,200);
}

Bootstrap::~Bootstrap()
{
    if(sharedMemory->isAttached())
        sharedMemory->detach();

    delete ui;
}

void Bootstrap::timerEvent(QTimerEvent *)
{
    fetchData();
    appendLog("Sync Finished");
}

void Bootstrap::updateToMemory()
{
    if(dataSource.isEmpty())
        return;

    if(sharedMemory->isAttached())
        sharedMemory->detach();

    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);

    QDataStream out(&buffer);
    out << dataSource;
    int size=buffer.size();
    if(!sharedMemory->create(size))
    {
        appendLog("SHM Update Failure: " + sharedMemory->errorString());
    }
    else{
        sharedMemory->lock();
        // 定义char变量 一个接受sharedMemory  一个接收buffer数据
        char *to = static_cast<char*>(sharedMemory->data());
        const char *from = buffer.data().constData();
        //共享内存段就是一段普通内存，用C语言标准函数memcpy()复制内存段。
        //将bufffer 数据写入共享内存中
        memcpy(to,from,qMin(size,sharedMemory->size()));
        //解锁共享内存段
        sharedMemory->unlock();
        appendLog("SHM Update Success");
    }
}

void Bootstrap::fetchData()
{
    if(!dataSource.isEmpty())
        dataSource.clear();

    QSqlQuery query;
    query.exec(QString("select entry,host,port,user,passwd,db from %1").arg(dsTable));
    while (query.next()) {
        QString entry=query.value(0).toString();
        if(entry.isEmpty())
            continue;

        QString host=query.value(1).toString();
        int port=query.value(2).toInt();
        if(port == 0)
            port=3306;
        QString user=query.value(3).toString();
        QString passwd=query.value(4).toString();
        QString db=query.value(5).toString();

        QJsonObject obj;
        obj.insert("entry",entry);
        obj.insert("host",host);
        obj.insert("port",port);
        obj.insert("user",user);
        obj.insert("passwd",passwd);
        obj.insert("db",db);
        dataSource.insert(entry,obj);
    }

    updateToMemory();
}

void Bootstrap::updateData(const QString &entry)
{
    QSqlQuery query;
    query.exec(QString("select host,port,user,passwd,db from %1 where entry='%2'")
               .arg(dsTable)
               .arg(entry));
    if (query.next()) {
        QString host=query.value(0).toString();
        int port=query.value(1).toInt();
        if(port == 0)
            port=3306;
        QString user=query.value(2).toString();
        QString passwd=query.value(3).toString();
        QString db=query.value(4).toString();

        QJsonObject obj;
        obj.insert("entry",entry);
        obj.insert("host",host);
        obj.insert("port",port);
        obj.insert("user",user);
        obj.insert("passwd",passwd);
        obj.insert("db",db);

        dataSource.insert(entry,obj);
    }

    updateToMemory();
}

void Bootstrap::createTray()
{
    trayMenu=new QMenu(this);
    trayMenu->addAction("DSEditor",this,&Bootstrap::toggleDSEditor);
    trayMenu->addAction("Log",this,&Bootstrap::toggleState);
    trayMenu->addSeparator();
    trayMenu->addAction("Sync",this,&Bootstrap::fetchData);
    trayMenu->addSeparator();
    trayMenu->addAction(QStringLiteral("退出"),QApplication::quit);

    tray=new QSystemTrayIcon(this);
    tray->setIcon(QIcon(":/home.ico"));
    tray->setContextMenu(trayMenu);
    tray->setToolTip(QString(SP_NAME) + QString(" ") + SP_VERSION);
    connect(tray,&QSystemTrayIcon::activated,this,&Bootstrap::trayActivated);
    tray->show();
}

void Bootstrap::toggleState()
{
    if(isVisible())
        hide();
    else
        show();
}

void Bootstrap::trayActivated(QSystemTrayIcon::ActivationReason reason)
{
    if(reason == QSystemTrayIcon::DoubleClick)
    {
        toggleDSEditor();
    }
}

void Bootstrap::toggleDSEditor()
{
    if(dsEditor == nullptr)
    {
        dsEditor=new DSEditor(this);
        connect(dsEditor,&DSEditor::sourceChanged,this,&Bootstrap::onSourceChanged);
    }

    if(!dsEditor->isVisible())
        dsEditor->show();
    else
        dsEditor->hide();
}

void Bootstrap::onSourceChanged()
{
    fetchData();
}

void Bootstrap::appendLog(const QString &event)
{
    ui->display->append(CurrentDateTime + QString(", ") + event + ";");
}
